편미분과 그래디언트

5.1절에서 논의된 미분은 스칼라 변수 $x \in \mathbb{R}$ 를 입력으로 받는 함수 $f$ 에 적용되었다. 이제부터는 함수 $f$ 가 하나 이상의 변수 $x \in \mathbb{R}^n$ 에 의존하는 일반적인 경우를 고려한다. 예를 들어 $f(x) = f(x_1, x_2)$ 와 같은 형태다. 다변수 함수에 대한 미분의 일반화된 형태가 바로 그라디언트(gradient)이다.
$\quad$ 우리는 한 번에 변수 하나만 변화시키고 나머지 변수들은 상수로 고정함으로써, $x$ 에 대한 함수 $f$ 의 그라디언트를 구한다. 이렇게 구한 편미분들을 모아놓은 것이 그라디언트가 된다.

정의 5.5 (편미분). $n$ 개의 변수 $x_1, \dots, x_n$ 을 가지는 함수 $f: \mathbb{R}^n \rightarrow \mathbb{R}, x \mapsto f(x), x \in \mathbb{R}^n$ 에 대하여, 우리는 편미분을 다음과 같이 정의한다.

$$ \frac{\partial f}{\partial x_1} = \lim_{h \to 0} \frac{f(x_1 + h, x_2, \dots, x_n) - f(x)}{h} $$
$$ \vdots \quad (5.39) $$
$$ \frac{\partial f}{\partial x_n} = \lim_{h \to 0} \frac{f(x_1, \dots, x_{n-1}, x_n + h) - f(x)}{h} $$

그리고 이들을 다음과 같은 행 벡터(row vector)로 모은다.

$$ \nabla_x f = \text{grad} f = \frac{df}{dx} = \left[ \frac{\partial f(x)}{\partial x_1} \quad \frac{\partial f(x)}{\partial x_2} \quad \cdots \quad \frac{\partial f(x)}{\partial x_n} \right] \in \mathbb{R}^{1 \times n}, \quad (5.40) $$

여기서 $n$ 은 변수의 개수이고, 1은 함수 $f$ 의 치역(공역)의 차원이다. 여기서 우리는 입력 벡터 $x = [x_1, \dots, x_n]^\top \in \mathbb{R}^n$ 를 열 벡터로 정의했다. 식 (5.40)의 행 벡터는 $f$ 의 그라디언트 또는 야코비안(Jacobian)이라 불리며, 이는 5.1절에서 다룬 미분을 일반화한 것이다.

참고. 야코비안에 대한 이 정의는 편미분들의 모음으로서 벡터 값을 가지는 함수의 야코비안에 대한 일반적인 정의의 특수한 경우이다. 이에 대해서는 5.3절에서 다시 다룰 것이다.
$\to$ 우리는 스칼라 미분의 결과를 그대로 사용할 수 있다. 왜냐하면 각 편미분은 결국 스칼라(하나의 변수)에 대한 미분이기 때문이다.

예제 5.6 (연쇄 법칙을 이용한 편미분)

함수 $f(x, y) = (x + 2y^3)^2$ 에 대하여, 우리는 다음과 같은 편미분을 얻는다.

$$ \frac{\partial f(x, y)}{\partial x} = 2(x + 2y^3) \frac{\partial}{\partial x}(x + 2y^3) = 2(x + 2y^3), \quad (5.41) $$
$$ \frac{\partial f(x, y)}{\partial y} = 2(x + 2y^3) \frac{\partial}{\partial y}(x + 2y^3) = 12(x + 2y^3)y^2. \quad (5.42) $$

여기서 우리는 편미분을 계산하기 위해 연쇄 법칙 (5.32)를 사용했다.

참고 (행 벡터로서의 그라디언트). 문헌에서 그라디언트 벡터를 열 벡터(column vector)로 정의하는 것은 드문 일이 아닌데, 이는 벡터가 일반적으로 열 벡터라는 관례를 따르는 것이다. 우리가 그라디언트 벡터를 행 벡터(row vector)로 정의하는 이유는 두 가지이다. 첫째, 우리는 그라디언트를 벡터 값을 가지는 함수 $f: \mathbb{R}^n \rightarrow \mathbb{R}^m$ 로 일관되게 일반화할 수 있다(이때 그라디언트는 행렬이 된다). 둘째, 우리는 그라디언트의 차원에 신경 쓰지 않고도 다변수 연쇄 법칙을 즉시 적용할 수 있다. 이 두 가지 요점은 5.3절에서 논의할 것이다.

예제 5.7 (그라디언트)

함수 $f(x_1, x_2) = x_1^2x_2 + x_1x_2^3 \in \mathbb{R}$ 에 대하여, 편미분(즉, $x_1$ 과 $x_2$ 에 대한 $f$ 의 미분)은 다음과 같다.

$$ \frac{\partial f(x_1, x_2)}{\partial x_1} = 2x_1x_2 + x_2^3 \quad (5.43) $$
$$ \frac{\partial f(x_1, x_2)}{\partial x_2} = x_1^2 + 3x_1x_2^2 \quad (5.44) $$

따라서 그라디언트는 다음과 같다.

$$ \frac{df}{dx} = \left[ \frac{\partial f(x_1, x_2)}{\partial x_1} \quad \frac{\partial f(x_1, x_2)}{\partial x_2} \right] = [2x_1x_2 + x_2^3 \quad x_1^2 + 3x_1x_2^2] \in \mathbb{R}^{1 \times 2}. \quad (5.45) $$

5.2.1 편미분의 기본 규칙

$x \in \mathbb{R}^n$ 인 다변수 경우에도, 우리가 학교에서 배운 기본적인 미분 규칙들(예: 합의 법칙, 곱의 법칙, 연쇄 법칙; 5.1.2절 참조)은 여전히 적용된다. 하지만 벡터 $x \in \mathbb{R}^n$ 에 대해 미분을 계산할 때는 주의가 필요하다. 이제 우리의 그라디언트는 벡터와 행렬을 포함하며, 행렬 곱셈은 교환 법칙이 성립하지 않기 때문이다(2.2.1절 참조). 즉, 순서가 중요하다.
$\quad$ 다음은 일반적인 곱의 법칙, 합의 법칙, 그리고 연쇄 법칙이다.
곱의 법칙 (Product rule):

$$ \frac{\partial}{\partial x}(f(x)g(x)) = \frac{\partial f}{\partial x}g(x) + f(x)\frac{\partial g}{\partial x} \quad (5.46) $$

합의 법칙 (Sum rule):

$$ \frac{\partial}{\partial x}(f(x) + g(x)) = \frac{\partial f}{\partial x} + \frac{\partial g}{\partial x} \quad (5.47) $$

연쇄 법칙 (Chain rule):

$$ \frac{\partial}{\partial x}(g \circ f)(x) = \frac{\partial}{\partial x}(g(f(x))) = \frac{\partial g}{\partial f} \frac{\partial f}{\partial x} \quad (5.48) $$

연쇄 법칙을 좀 더 자세히 살펴보자. 연쇄 법칙 (5.48)은 행렬 곱셈이 정의되기 위해 이웃한 차원이 일치해야 한다는 행렬 곱셈 규칙과 어느 정도 닮아 있다(2.2.1절 참조). 왼쪽에서 오른쪽으로 갈 때, 연쇄 법칙은 유사한 성질을 보인다. $\partial f$ 는 첫 번째 인수의 ‘분모’에 나타나고 두 번째 인수의 ‘분자’에 나타난다. 만약 이 인수들을 서로 곱하면, 곱셈이 정의된다. 즉 $\partial f$ 의 차원이 일치하여 $\partial f$ 가 ‘상쇄(약분)’되는 것처럼 보이고, 결과적으로 $\partial g/\partial x$ 가 남게 된다.
$\to$ 이것(약분처럼 사라지는 것)은 직관일 뿐이며 수학적으로 정확한 표현은 아니다. 왜냐하면 편미분은 분수(fraction)가 아니기 때문이다.

5.2.2 연쇄 법칙

두 변수 $x_1, x_2$ 를 가지는 함수 $f: \mathbb{R}^2 \rightarrow \mathbb{R}$ 를 고려해 보자. 더 나아가, $x_1(t)$ 와 $x_2(t)$ 는 그 자체로 $t$ 에 대한 함수라고 하자. $t$ 에 대한 $f$ 의 그라디언트를 계산하기 위해서는 다음과 같이 다변수 함수에 대한 연쇄 법칙 (5.48)을 적용해야 한다.

$$ \frac{df}{dt} = \left[ \frac{\partial f}{\partial x_1} \quad \frac{\partial f}{\partial x_2} \right] \begin{bmatrix} \frac{\partial x_1(t)}{\partial t} \\ \frac{\partial x_2(t)}{\partial t} \end{bmatrix} = \frac{\partial f}{\partial x_1} \frac{\partial x_1}{\partial t} + \frac{\partial f}{\partial x_2} \frac{\partial x_2}{\partial t}, \quad (5.49) $$

여기서 $d$ 는 그라디언트(또는 전미분)를 나타내고 $\partial$ 는 편미분을 나타낸다.

예제 5.8 $f(x_1, x_2) = x_1^2 + 2x_2$ 이고, $x_1 = \sin t$ , $x_2 = \cos t$ 인 경우를 고려해 보자. 그러면 다음을 얻는다.

$$ \frac{df}{dt} = \frac{\partial f}{\partial x_1} \frac{\partial x_1}{\partial t} + \frac{\partial f}{\partial x_2} \frac{\partial x_2}{\partial t} \quad (5.50a) $$
$$ = 2 \sin t \frac{\partial \sin t}{\partial t} + 2 \frac{\partial \cos t}{\partial t} \quad (5.50b) $$
$$ = 2 \sin t \cos t - 2 \sin t = 2 \sin t(\cos t - 1) \quad (5.50c) $$

이것이 $t$ 에 대한 $f$ 의 미분이다.

$\quad$ 만약 $f(x_1, x_2)$ 가 $x_1$ 과 $x_2$ 의 함수이고, $x_1(s, t)$ 와 $x_2(s, t)$ 가 그 자체로 두 변수 $s$ 와 $t$ 의 함수라면, 연쇄 법칙은 다음과 같은 편미분들을 산출한다.

$$ \frac{\partial f}{\partial s} = \frac{\partial f}{\partial x_1} \frac{\partial x_1}{\partial s} + \frac{\partial f}{\partial x_2} \frac{\partial x_2}{\partial s}, \quad (5.51) $$
$$ \frac{\partial f}{\partial t} = \frac{\partial f}{\partial x_1} \frac{\partial x_1}{\partial t} + \frac{\partial f}{\partial x_2} \frac{\partial x_2}{\partial t}, \quad (5.52) $$

그리고 그라디언트는 행렬 곱셈으로 얻어진다.

$$ \frac{df}{d(s, t)} = \frac{\partial f}{\partial x} \frac{\partial x}{\partial (s, t)} = \underbrace{\left[ \frac{\partial f}{\partial x_1} \quad \frac{\partial f}{\partial x_2} \right]}_{= \frac{\partial f}{\partial x}} \underbrace{\begin{bmatrix} \frac{\partial x_1}{\partial s} & \frac{\partial x_1}{\partial t} \\ \frac{\partial x_2}{\partial s} & \frac{\partial x_2}{\partial t} \end{bmatrix}}_{= \frac{\partial x}{\partial (s, t)}}. \quad (5.53) $$

연쇄 법칙을 행렬 곱셈으로 작성하는 이 간결한 방식은 그라디언트가 행 벡터로 정의될 때만 의미가 통한다. 그렇지 않으면, 행렬 차원을 맞추기 위해 그라디언트를 전치(transpose)하기 시작해야 한다. 그라디언트가 벡터나 행렬인 경우에는 여전히 간단할 수 있지만, 그라디언트가 텐서(tensor)가 되면 전치는 더 이상 사소한 문제가 아니다.
참고 (그라디언트 구현의 정확성 검증). 차분 몫의 극한으로서 편미분의 정의(5.39 참조)는 컴퓨터 프로그램에서 그라디언트의 정확성을 수치적으로 확인할 때 유용하게 쓰일 수 있다. 그라디언트를 계산하고 구현할 때, 우리는 유한 차분(finite differences)을 사용하여 우리의 계산과 구현을 수치적으로 테스트할 수 있다. 우리는 $h$ 값을 작게(예: $h = 10^{-4}$ ) 선택하고, (5.39)에서 얻은 유한 차분 근사값과 우리가 구현한 (해석적) 그라디언트를 비교한다. 만약 오차가 작다면, 우리의 그라디언트 구현은 아마도 올바를 것이다. 여기서 “작다”는 것은 다음을 의미할 수 있다.

$$ \sqrt{\frac{\sum_i (dh_i - df_i)^2}{\sum_i (dh_i + df_i)^2}} < 10^{-6} $$

여기서 $dh_i$ 는 유한 차분 근사값이고 $df_i$ 는 $i$ 번째 변수 $x_i$ 에 대한 $f$ 의 해석적(공식으로 구한) 그라디언트이다.

$\to$ gradient checking은 pytorch나 tensorflow같은 프레임워크 내부에서 그래디언트를 연산하는 backword()함수에 대한 연산이 실제로 수치 미분의 결과와 일치하는지 검산하는 것이다. 수치 미분은 $x$ 에 아주 작은 숫자 $h=0.0001$ (learning rate와는 다른 개념이다.)을 더해서 $f(x+h)$ 를 계산하여 $(f(x+h) - f(x)) / h$ 를 구하는 과정이다.